/**
 * @file rng.h
 * @brief Random Number Generator (RNG) interface.
 *
 * This header file provides an interface for RNG operations, including creating
 * RNG objects from seeds or state, getting random numbers, and managing RNG
 * state.
 *
 * @example rng.cc
 */
#ifndef TACHYON_C_CRYPTO_RANDOM_RNG_H_
#define TACHYON_C_CRYPTO_RANDOM_RNG_H_

#include <stddef.h>
#include <stdint.h>

#include "tachyon/c/export.h"

#define TACHYON_RNG_XOR_SHIFT 0
#define TACHYON_RNG_CHA_CHA20 1

/**
 * @struct tachyon_rng
 * @brief Represents a random number generator.
 */
struct tachyon_rng {
  uint8_t type;
  void* extra;
};

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Creates a random number generator from the given seed.
 * @param type The type of random number generator.
 * @param seed Seed data in array of bytes.
 * @param seed_len The length of the seed.
 * @return Pointer to the newly created random number generator.
 */
TACHYON_C_EXPORT tachyon_rng* tachyon_rng_create_from_seed(uint8_t type,
                                                           const uint8_t* seed,
                                                           size_t seed_len);

/**
 * @brief Creates a random number generator from the given state.
 *
 * This function allows the creation of a random number generator (RNG) with a
 * predefined internal state, enabling reproducible RNG sequences.
 *
 * @param type The random number generator type.
 * @param state The array representing the RNG's internal state.
 * @param state_len The length of the state array.
 * @return Pointer to the newly created random number generator.
 */
TACHYON_C_EXPORT tachyon_rng* tachyon_rng_create_from_state(
    uint8_t type, const uint8_t* state, size_t state_len);

/**
 * @brief Destroys a random number generator.
 *
 * Frees the resources associated with the random number generator. After
 * calling this function, the rng pointer should not be used anymore.
 *
 * @param rng A pointer to the random number generator to destroy.
 */
TACHYON_C_EXPORT void tachyon_rng_destroy(tachyon_rng* rng);

/**
 * @brief Generates a 32-bit unsigned integer from the random number generator.
 *
 * This function returns a randomly generated 32-bit unsigned integer using the
 * specified RNG. The randomness and distribution of the number depend on the
 * RNG's implementation.
 *
 * @param rng A pointer to the random number generator.
 * @return A 32-bit unsigned integer generated by the RNG.
 */
TACHYON_C_EXPORT uint32_t tachyon_rng_get_next_u32(tachyon_rng* rng);

/**
 * @brief Generates a 64-bit unsigned integer from the random number generator.
 *
 * This function returns a randomly generated 64-bit unsigned integer using the
 * specified RNG. The randomness and distribution of the number depend on the
 * RNG's implementation.
 *
 * @param rng A pointer to the random number generator.
 * @return A 64-bit unsigned integer generated by the RNG.
 */
TACHYON_C_EXPORT uint64_t tachyon_rng_get_next_u64(tachyon_rng* rng);

/**
 * @brief Retrieves the current state of the random number generator.
 *
 * This function is used to obtain the current internal state of the RNG. This
 * state can be used to create a new RNG instance that continues generating
 * random numbers from the same point.
 *
 * If the @p state parameter is NULL, the function populates @p state_len with
 * the necessary length to hold the state. This can be used to allocate enough
 * storage before calling the function again with a non-NULL @p state.
 *
 * @param rng A const pointer to the random number generator.
 * @param state A pointer to the buffer where the RNG's state will be stored. If
 * NULL, the function only populates @p state_len.
 * @param state_len A pointer to a variable where the length of the state will
 * be stored. If @p state is not NULL, it should be initialized to the size of
 * the buffer pointed to by @p state.
 */
TACHYON_C_EXPORT void tachyon_rng_get_state(const tachyon_rng* rng,
                                            uint8_t* state, size_t* state_len);

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // TACHYON_C_CRYPTO_RANDOM_RNG_H_
